<!DOCTYPE html>
<html>
<head>
  <title>unique去重</title>
</head>
<body>
<div id='container' style="height:300px;width:100%;background-color:black;color: white;font-size:23px;text-align: center;line-height: 300px;">
  0
</div>
<script type="text/javascript">

  // 参考：https://github.com/mqyqingfeng/Blog/blob/master/articles/%E4%B8%93%E9%A2%98%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/JavaScript%E4%B8%93%E9%A2%98%E4%B9%8B%E6%95%B0%E7%BB%84%E5%8E%BB%E9%87%8D.md

  // 第一版（原始）
  function unique1(array) {
    // res用来存储结果
    var res = [];
    for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++ ) {
            if (array[i] === res[j]) {
                break;
            }
        }
        // 如果array[i]是唯一的，那么执行完循环，j等于resLen
        if (j === resLen) {
            res.push(array[i])
        }
    }
    return res;
  }

  // 第二版(第一版的简略版)
  function unique2(array) {
    var res = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var current = array[i];
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res;
  }


  // 第三版
  // isSorted 我们根据一个参数 isSorted 判断传入的数组是否是已排序的，如果为 true
  function unique3(array, isSorted) {
      var res = [];
      var seen = [];

      for (var i = 0, len = array.length; i < len; i++) {
          var value = array[i];
          if (isSorted) {
              if (!i || seen !== value) {
                  res.push(value)
              }
              seen = value;
          }
          else if (res.indexOf(value) === -1) {
              res.push(value);
          }
      }
      return res;
  }

  // 第四版
  // iteratee 英文释义：迭代 重复
  function unique4(array, isSorted, iteratee) {
    var res = [];
    var seen = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var value = array[i];
        var computed = iteratee ? iteratee(value, i, array) : value;
        if (isSorted) {
            if (!i || seen !== value) {
                res.push(value)
            }
            seen = value;
        } else if (iteratee) {
            if (seen.indexOf(computed) === -1) {
                seen.push(computed);
                res.push(value);
            }
        } else if (res.indexOf(value) === -1) {
            res.push(value);
        }
    }
    return res;
  }

  // ES5 提供了 filter 方法，我们可以用来简化外层循环：

  function unique5(array) {
      var res = array.filter(function(item, index, array){
          return array.indexOf(item) === index;
      })
      return res;
  }

// -------------------------Object 键值对方式去重--------------------------------------
  function unique6(array) { // 不推荐
      var obj = {};
      return array.filter(function(item, index, array){
          return obj.hasOwnProperty(item) ? false : (obj[item] = true)
      })
  }
  // 注意：
  // 我们可以发现，是有问题的，因为 1 和 '1' 是不同的，但是这种方法会判断为同一个值，这是因为对象的键值只能是字符串，所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题：

  function unique7(array) { // 不推荐
      var obj = {};
      return array.filter(function(item, index, array){
          return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
      })
  }

  // 注意，即便如此，我们依然无法正确区分出两个对象，比如 {value: 1} 和 {value: 2}，因为 typeof item + item 的结果都会是 object[object Object]，不过我们可以使用 JSON.stringify 将对象序列化：

  function unique8(array) { // 推荐
    var obj = {};
    return array.filter(function(item, index, array){
        console.log(typeof item + JSON.stringify(item))
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
  }
// -------------------------ES6方式--------------------------------------
function unique9(array) {
  return Array.from(new Set(array));
}

function unique10(array) {
    return [...new Set(array)];
}
// 简化
var unique10 = (a) => [...new Set(a)]

// 此外，如果用 Map 的话：
function unique11 (arr) {
  const seen = new Map()
  return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}


  var array = [1, 1, '1', '1'];
  var array2 = [1, 2, '1', 2, 1];
  var array3 = [1, 1, '1', 2, 2];
  var array4 = [1, 1, 'a', 'A', 2, 2];
  var array5 = [1, 2, 1, 1, '1'];
  var array6 = [1, 2, 1, 1, '1'];
  var array7 = [1, 2, 1, 1, '1'];
  var array8 = [{value: 1}, {value: 1}, {value: 2}];
  var array9 = [1, 2, 1, 1, '1'];

  // console.log(unique1(array)); // [1, "1"]
  // console.log(unique2(array)); // [1, "1"]
  // console.log(unique3(array2)); // [1, 2, "1"]
  // console.log(unique3(array3, true)); // [1, "1", 2]
  // 但是，如果isSorted为true, console.log(unique3(array2, true)); // [1, 2, "1", 2, 1]
  // console.log(unique(array4, false, function(item){
  //   return typeof item == 'string' ? item.toLowerCase() : item
  // })); // [1, "a", 2]
  // console.log(unique5(array5)); // [1,2,'1']
  // console.log(unique6(array6)); // 不推荐 [1, 2]
  // console.log(unique7(array7)); // 推荐 [1, 2, "1"]
  console.log(unique8(array8)); // [{value: 1}, {value: 2}]
  console.log(unique9(array9)); // [1, 2, "1"]
  console.log(unique10(array9)); // [1, 2, "1"]


</script>
</body>
</html>
